<?php
declare (strict_types=1);

namespace app\common\model;

use app\common\facade\Jpush;
use think\facade\Cache;
use think\facade\Event;
use think\facade\Log;

class Product extends Base
{
    protected $name = 'product';

    public function cate1()
    {
        return $this->hasOne(ProductCate::class, 'id', 'cate_1')->field('id,title');
    }

    public function cate2()
    {
        return $this->hasOne(ProductCate::class, 'id', 'cate_2')->field('id,title');
    }

    public function cate3()
    {
        return $this->hasOne(ProductCate::class, 'id', 'cate_3')->field('id,title');
    }

    public function discount()
    {
        return $this->hasOne(Product::class, 'id', 'give_discount_pid')->field('id,title,vip_price,icon');
    }

    public function business()
    {
        return $this->hasOne(Business::class, 'id', 'business_id')
            ->field('id,title,logo,mobile,customer_tel,full_address,fans,contacts,describe_score,logistics_score,service_score,type');
    }

    public function user()
    {
        return $this->hasOne(User::class, 'id', 'uid')
            ->field('id,nickname,real_name,mobile,level_id,level_bonus_id,level_video_id,agent_level,syn_level,province,city,district');
    }

    public function getExamineStatusTextAttr($value, $data): string
    {
        switch ($data['examine_status']) {
            case 1:
                return "待审核";
            case 2:
                return "已通过";
            case 3:
                return "已驳回";
            default:
                return "未知";
        }
    }

    public function getExamineTimeAttr($value)
    {
        return $value ? date('Y-m-d H:i:s', $value) : '';
    }

    public function getImagesAttr($value)
    {
        return $value ? explode(',', $value) : [];
    }

    public function getContentImagesAttr($value)
    {
        return $value ? explode(',', $value) : [];
    }


    public static function _save($param, $business = '')
    {
        return self::_saveSpec($param);
    }


    public static function _saveSpec($param, $business = '', $msg = '')
    {
        parent::startTrans();
        try {
            $specData = $param['specData'];
            $skus = $param['skus'];
            foreach ($skus as $k=>$sku) {
                if(isset($sku['currency'])
                    && isset($sku['chain_bean'])
                    && isset($sku['love_bean'])
                    && isset($sku['vip_integ'])
                    && isset($sku['red_coin'])
                    && isset($sku['profit'])
                    && isset($sku['vip_profit'])
                    && isset($sku['cost'])){
                    if($sku['currency']
                        + $sku['chain_bean']
                        + $sku['love_bean']
                        + $sku['vip_integ']
                        + $sku['red_coin']
                        + $sku['profit']
                        + $sku['vip_profit']
                        + $sku['cost'] > $sku['vip_price']){
                        $spec = SpecItem::where('id', $k)->value('name');
                        return ['code' => -1, 'msg' => "“{$spec}”总抵扣、总利润与成本之和不可超过VIP价格"];
                    }
                }

            }
            $param['icon'] = isset($param['images'][0]) ? $param['images'][0] : '';
            $param['images'] = !empty($param['images']) ? implode(',', $param['images']) : '';
            $param['content_images'] = !empty($param['content_images']) ? implode(',', $param['content_images']) : '';
            $param['service'] = !empty($param['service']) ? implode(',', $param['service']) : '';
            if(isset($param['is_business']) && $param['is_business'] == 1){
                $param['examine_status'] = 1;
            }

            unset($param['specData']);
            unset($param['skus']);
            unset($param['file']);
            if (!isset($param['business_id']) && $business) {
                $param['business_id'] = $business->id;
            }
            if (isset($param['id']) && $param['id']) {
                $product = parent::update($param);
                $product->operation = 'save';
                //监听无效商品
                Event::trigger('InvalidProductCart', ['pid' => $param['id']]);
            } else {
                $product = parent::create($param);
                $product->operation = 'create';
            }

            //设置商品规格数据
            $result = ProductSpecData::setSpecData($product->id, $specData, $business);
            if (!$result) {
                parent::rollback();
                return ['code' => -1, 'msg' => '加载失败，error:1'];
            }

            //设置商品规格值
            $result = ProductSpecValue::setSpecValue($product->id, $skus, $business);
            if (!$result) {
                parent::rollback();
                return ['code' => -1, 'msg' => '加载失败，error:2'];
            }
            foreach ($result as $k => $v) {
                $product->$k = $v;
            }
            $product->save();

            parent::commit();
            if ($business) {
                return ['code' => 1, 'msg' => $msg];
            } else {
                Event::trigger('Logs', $product);
                return ['code' => 1, 'msg' => '已保存'];
            }

        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function recordLog($model)
    {

        $emp_id = session('admin_id');
        $emp_name = Admin::where('id', $emp_id)->value('admin_name');
        $title = '商品';
        $operation = getOperation($model->operation);
        if (in_array($model->operation, ['updateAll', 'deleteAll'])) {
            $msg = $operation . '【' . $title . '】' . '标识ID【' . implode(',', $model->ids) . '】';
            Logs::adds($msg, $emp_id, $emp_name);
        } else {
            $msg = $operation . '【' . $title . '】' . '标识ID【' . $model->id . '】标题【' . $model->title . '】';
            Logs::adds($msg, $emp_id, $emp_name);
        }
    }


    public static function submit($param, $user): array
    {
        try {
            $all = [];
            $info = parent::where(['id' => $param['id'], 'is_del' => 0, 'status' => 1])->find();
            if (empty($info)) {
                return ['code' => -1, 'msg' => '商品不存在或已下架'];
            }
            if (!$info->price || $info->price <= 0) {
                return ['code' => -1, 'msg' => '商品价格错误'];
            }
            if ($info->stock < $param['num']) {
                return ['code' => -1, 'msg' => '商品库存不足'];
            }
            $all[] = [
                'pid'    => $info->id,
                'num'    => $param['num'],
                'cate_1' => $info->cate_1,
            ];

            Cache::set('tsOrder_' . $user->id, json_encode($all));

            return ['code' => 4, 'msg' => 'success', 'url' => url('order/index')->build()];

        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    public function getIsAuditAttr($value)
    {
        switch ($value) {
            case 1:
                return '待审核';
            case 2:
                return '已通过';
            case 3:
                return '已驳回';
            default:
                return '未知';
        }
    }

    public static function examineSave($param, $admin)
    {
        $info = parent::where('id', $param['id'])->find();
        if (empty($info)) {
            return ['code' => -1, 'msg' => '商品不存在'];
        }
        if ($info->examine_status != 1) {
            return ['code' => -1, 'msg' => '该商品已审核'];
        }
        if (!$param['type']) {
            return ['code' => -1, 'msg' => '请选择要审核的操作'];
        }
        if ($param['type'] == 3 && !$param['examine_msg']) {
            return ['code' => -1, 'msg' => '请填写驳回原因'];
        }
        parent::startTrans();
        try {
            $info->examine_status = $param['type'];
            $info->examine_time = time();
            $info->examine_msg = isset($param['examine_msg']) ? $param['examine_msg'] : '';
            $info->examine_admin_id = $admin->id;
            $info->examine_admin_name = $admin->admin_name;
            $info->status = 0;
            $info->save();

//            $res = self::_saveSpec($param);
//            if ($res['code'] != 1) {
//                parent::rollback();
//                return ['code' => -1, 'msg' => '审核失败：' . $res['msg']];
//            }
            parent::commit();

            //self::jpush($info);

            return ['code' => 1, 'msg' => '已审核'];

        } catch (\Exception $e) {
            parent::rollback();
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    private static function jpush($info)
    {
        //测试商品推送
        $content = "商品".$info['title']."已上架";
        $parameter = ['event_type' => 1004, 'sub_event_type' => 1102, 'id'=>$info->id];
        $extra = ['extras' => ['parameter' => json_encode($parameter)]];

        Jpush::sendAllNotify($content, $extra);
    }

    /**
     * 下架商品定时上架
     */
    public static function autoShelf(): array
    {
        try{
            self::where('status',0)->where('auto_shelf_time', '<>', null)->select()->each(function ($item){
                if(date("Y-m-d H:i:s") >= $item->auto_shelf_time){
                    $item->status = 1;
                    $item->auto_shelf_time = null;
                    $item->save();
                }
            });
            return ['code' => 1, 'msg' => 'done'];
        }catch (\Exception $e){
            Log::write("下架商品定时上架失败：".$e->getMessage());
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    /**
     * 增加商品数据统计(定时任务，每天凌晨00:10执行)
     */
    public static function addStatistics(): array
    {
        OrderProduct::with(['user'])->whereDay('create_time', 'yesterday')->select()->each(function ($item){//$order->create_time
            if($item->user->district){
                if($month = StatisticsProductMonth::where(['product_id'=>$item->pid, 'month'=>date("Y-m", strtotime($item->create_time))])->find()){
                    $month->user_count ++;
                    $month->consume_sum += $item->real_amount;
                }else{
                    $month = StatisticsProductMonth::create([
                        'product_id' => $item->pid,
                        'product_name' => $item->title,
                        'user_count' => 1,
                        'consume_sum' => $item->vip_price,
                        'year' => date("Y", strtotime($item->create_time)),
                        'month' => date("Y-m", strtotime($item->create_time)),
                    ]);
                }
                $userRate = self::getRate($item, 'user', 'month', $month->user_count);
                $consumeRate = self::getRate($item, 'consume', 'month', 0, $month->consume_sum);

                $month->user_add = $userRate[0];
                $month->user_rate = $userRate[1];
                $month->consume_add = $consumeRate[0];
                $month->consume_rate = $consumeRate[1];

                $month->save();

                if($year = StatisticsProductYear::where(['product_id'=>$item->pid, 'year'=>date("Y", strtotime($item->create_time))])->find()){
                    $year->user_count ++;
                    $year->consume_sum += $item->real_amount;
                }else{
                    $year = StatisticsProductYear::create([
                        'product_id' => $item->pid,
                        'product_name' => $item->title,
                        'user_count' => 1,
                        'consume_sum' => $item->vip_price,
                        'year' => date("Y", strtotime($item->create_time)),
                    ]);
                }

                $userRate = self::getRate($item, 'user', 'year', $year->user_count);
                $consumeRate = self::getRate($item, 'consume', 'year', 0, $year->consume_sum);

                $year->user_add = $userRate[0];
                $year->user_rate = $userRate[1];
                $year->consume_add = $consumeRate[0];
                $year->consume_rate = $consumeRate[1];

                $year->save();
            }
        });

        return ['code'=>1, 'msg'=>'done'];
    }

    private static function getRate($order, $type, $time, $user_count=0, $consume_sum=0)
    {
        if($time == 'month'){
            $last = StatisticsProductMonth::where(['product_id'=>$order->pid, 'month'=>date("Y-m", strtotime("-1 month", strtotime($order->create_time)))])->find();
        }else{
            $last = StatisticsProductYear::where(['product_id'=>$order->pid, 'year'=>date("Y", strtotime("-1 year", strtotime($order->create_time)))])->find();
        }

        if($type == 'user'){
            $add = $last ? $user_count - $last->user_count : $user_count;
            $rate = $last && $last->user_count > 0 ? round(100*$add/$last->user_count, 2) : '0.00';
        }else{
            $add = $last ? $consume_sum - $last->consume_sum : $consume_sum;
            $rate = $last && $last->consume_sum > 0 ? round(100*$add/$last->consume_sum, 2) : '0.00';
        }

        return [$add, $rate];
    }

    public static function _all($map, $param, $hasOne, $like = [], $order = 'create_time,desc', $append = [], $filed = '*', $export = false): array
    {
        try {
            $page = $param['page'] ?? 1;
            $limit = $param['limit'] ?? 10;

            !$order && $order = 'create_time,desc';

            if(!isset($map['is_del'])){
                $map['is_del'] = 0;
            }

            if(!empty($map['status'])){
                $map['status'] == 2 && $map['status'] = 0;
            }

            $that = parent::where($map);

            if ($hasOne) {
                $that = $that->with($hasOne);
            }

            if (isset($param['times']) && $param['times']) {
                $times = explode(' - ', $param['times']);
                $that->whereBetweenTime('create_time', strtotime($times[0]), strtotime($times[1]));
            }

            if (isset($param['otherTimes']) && $param['otherTimes']) {
                foreach ($param['otherTimes'] as $k => $v) {
                    if (empty($v)) continue;
                    $decode = explode(' - ', $v);
                    $that->whereBetweenTime($k, strtotime($decode[0]), strtotime($decode[1]));
                }
            }

            foreach ($like as $v) {
                foreach ($v as $key => $vo) {
                    $that->whereLike($key, '%' . trim($vo) . '%');
                }
            }

            $order = explode(',', $order);
            if ($export) {
                $list = $that->field($filed)->order($order[0], $order[1])->select();
                $count = '';
                if (!empty($append)) {
                    $list->append($append);
                }

            } else {
                if($param['name'] == 'Product_examine'){
                    $list = $that->page(intval($page), intval($limit))->field($filed)->order('examine_status', 'asc')->order($order[0], $order[1])->select();
                }else{
                    $list = $that->page(intval($page), intval($limit))->field($filed)->order($order[0], $order[1])->select();
                }
                $count = getCount($that->fetchSql()->select());
                if (!empty($append)) {
                    $list->append($append);
                }
            }
            return ['code' => 0, 'data' => $list, 'count' => $count];
        } catch (\Exception $e) {
            dump($e);
            die;
            return [];
        }
    }

    /**
     * @param array $map - 查询条件，数组格式
     * @param string $field - 查询字段，默认*
     * @param int $page - 当前页
     * @param int $limit - 每页条数，默认20
     * @param bool $merge - 是否合并is_del，status等公共状态查询条件
     * @param array $with - 是否关键查询
     * @return array
     * 原点 2021年12月22日11:26:47 分页获取数据
     */
    public static function getPageList($map = [],
                                       $field = '*',
                                       $page = 1,
                                       $limit = 20,
                                       $merge = true,
                                       $with = [],
                                       $in = [],
                                       $sort = [],
                                       $like = [],
                                       $time = [], $withoutField = '', $append = [])
    {
        try {

            $map = $merge ? array_merge($map, ['is_del' => 0, 'status' => 1]) : $map;

            $leader = 0;
            if(isset($map['leader'])){
                $leader = $map['leader'];
                unset($map['leader']);
            }
            $that = !empty($with) ? parent::with($with)->where($map) : parent::where($map);
            if(0 == $leader){
                $that->where('cate_1', '<>', 3);
            }
            if (!empty($like)) {
                $that->whereLike($like['field'], '%' . $like['keyword'] . '%');
            }
            if ($time) {
                foreach ($time as $k => $v) {
                    $times = explode(' - ', $v['value']);
                    $that->whereBetweenTime($v['key'], $times[0], $times[1]);
                }
            }
            if (!empty($in)) {
                foreach ($in as $k => $v) {
                    $that->whereIn($k, $v);
                }
            }
            if ($withoutField) {
                $that->withoutField($withoutField);
            } else {
                $that->field($field);
            }

            $that->page(intval($page), intval($limit));

            if (!$sort) {
                $that->order($merge ? 'sort' : 'create_time', 'desc');
            } else {
                $that->order($sort['key'], $sort['value']);
            }

            $list = $that->select();
            if ($append) {
                $list->append($append);
            }

            return ['code' => 1, 'msg' => 'success', 'data' => $list];

        } catch (\Exception $e) {

            return ['code' => $e->getCode(), 'msg' => $e->getMessage()];

        }
    }

    /**
     * 商品抽奖次数定时清0
     */
    public static function prizeProductTimes()
    {
        list(, $endTime) = explode(',', Cache::get('system')['prize_times']);
        if(time() > $endTime){
            Prize::where('product_id', '>', 0)->select()->each(function ($item){
                Cache::set('prize_times_pid_'.$item->product_id, 0);
            });
        }

        return ['code'=>1, 'msg'=>'done'];
    }
}
